const path = require("path");
const buble = require("rollup-plugin-buble");
const alias = require("rollup-plugin-alias");
const cjs = require("rollup-plugin-commonjs");
const replace = require("rollup-plugin-replace");
const node = require("rollup-plugin-node-resolve");
const flow = require("rollup-plugin-flow-no-whitespace");
const version = process.env.VERSION || require("../package.json").version;
const weexVersion =
  process.env.WEEX_VERSION ||
  require("../packages/weex-vue-framework/package.json").version;
const featureFlags = require("./feature-flags");

const banner =
  "/*!\n" +
  ` * Vue.js v${version}\n` +
  ` * (c) 2014-${new Date().getFullYear()} Evan You\n` +
  " * Released under the MIT License.\n" +
  " */";

const weexFactoryPlugin = {
  intro() {
    return "module.exports = function weexFactory (exports, document) {";
  },
  outro() {
    return "}";
  },
};
// alias.js 别名
const aliases = require("./alias");
// @to 
const resolve = (p) => {
  const base = p.split("/")[0];
  if (aliases[base]) {
    return path.resolve(aliases[base], p.slice(base.length + 1));
  } else {
    return path.resolve(__dirname, "../", p);
  }
};

// 对象 属性-环境变量的值 web-full-dev
const builds = {
  // Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify
  "web-runtime-cjs-dev": {
    entry: resolve("web/entry-runtime.js"),
    dest: resolve("dist/vue.runtime.common.dev.js"),
    format: "cjs",
    env: "development",
    banner,
  },
  "web-runtime-cjs-prod": {
    entry: resolve("web/entry-runtime.js"),
    dest: resolve("dist/vue.runtime.common.prod.js"),
    format: "cjs",
    env: "production",
    banner,
  },
  // Runtime+compiler CommonJS build (CommonJS)
  "web-full-cjs-dev": {
    entry: resolve("web/entry-runtime-with-compiler.js"),
    dest: resolve("dist/vue.common.dev.js"),
    format: "cjs",
    env: "development",
    alias: { he: "./entity-decoder" },
    banner,
  },
  "web-full-cjs-prod": {
    entry: resolve("web/entry-runtime-with-compiler.js"),
    dest: resolve("dist/vue.common.prod.js"),
    format: "cjs",
    env: "production",
    alias: { he: "./entity-decoder" },
    banner,
  },
  // Runtime only ES modules build (for bundlers)
  "web-runtime-esm": {
    entry: resolve("web/entry-runtime.js"),
    dest: resolve("dist/vue.runtime.esm.js"),
    format: "es",
    banner,
  },
  // Runtime+compiler ES modules build (for bundlers)
  "web-full-esm": {
    entry: resolve("web/entry-runtime-with-compiler.js"),
    dest: resolve("dist/vue.esm.js"),
    format: "es",
    alias: { he: "./entity-decoder" },
    banner,
  },
  // Runtime+compiler ES modules build (for direct import in browser)
  "web-full-esm-browser-dev": {
    entry: resolve("web/entry-runtime-with-compiler.js"),
    dest: resolve("dist/vue.esm.browser.js"),
    format: "es",
    transpile: false,
    env: "development",
    alias: { he: "./entity-decoder" },
    banner,
  },
  // Runtime+compiler ES modules build (for direct import in browser)
  "web-full-esm-browser-prod": {
    entry: resolve("web/entry-runtime-with-compiler.js"),
    dest: resolve("dist/vue.esm.browser.min.js"),
    format: "es",
    transpile: false,
    env: "production",
    alias: { he: "./entity-decoder" },
    banner,
  },
  // runtime-only build (Browser)
  "web-runtime-dev": {
    entry: resolve("web/entry-runtime.js"),
    dest: resolve("dist/vue.runtime.js"),
    format: "umd",
    env: "development",
    banner,
  },
  // runtime-only production build (Browser)
  "web-runtime-prod": {
    entry: resolve("web/entry-runtime.js"),
    dest: resolve("dist/vue.runtime.min.js"),
    format: "umd",
    env: "production",
    banner,
  },
  // Runtime+compiler development build (Browser)
  // 打包配置文件基础信息 @to
  "web-full-dev": {
    // 入口  resolve：转为绝对路径
    entry: resolve("web/entry-runtime-with-compiler.js"),
    // 出口
    dest: resolve("dist/vue.js"),
    // 模块格式
    format: "umd",
    // 打包环境
    env: "development",
    // 别名
    alias: { he: "./entity-decoder" },
    // 文件头
    banner,
  },
  // Runtime+compiler production build  (Browser)
  "web-full-prod": {
    entry: resolve("web/entry-runtime-with-compiler.js"),
    dest: resolve("dist/vue.min.js"),
    format: "umd",
    env: "production",
    alias: { he: "./entity-decoder" },
    banner,
  },
  // Web compiler (CommonJS).
  "web-compiler": {
    entry: resolve("web/entry-compiler.js"),
    dest: resolve("packages/vue-template-compiler/build.js"),
    format: "cjs",
    external: Object.keys(
      require("../packages/vue-template-compiler/package.json").dependencies
    ),
  },
  // Web compiler (UMD for in-browser use).
  "web-compiler-browser": {
    entry: resolve("web/entry-compiler.js"),
    dest: resolve("packages/vue-template-compiler/browser.js"),
    format: "umd",
    env: "development",
    moduleName: "VueTemplateCompiler",
    plugins: [node(), cjs()],
  },
  // Web server renderer (CommonJS).
  "web-server-renderer-dev": {
    entry: resolve("web/entry-server-renderer.js"),
    dest: resolve("packages/vue-server-renderer/build.dev.js"),
    format: "cjs",
    env: "development",
    external: Object.keys(
      require("../packages/vue-server-renderer/package.json").dependencies
    ),
  },
  "web-server-renderer-prod": {
    entry: resolve("web/entry-server-renderer.js"),
    dest: resolve("packages/vue-server-renderer/build.prod.js"),
    format: "cjs",
    env: "production",
    external: Object.keys(
      require("../packages/vue-server-renderer/package.json").dependencies
    ),
  },
  "web-server-renderer-basic": {
    entry: resolve("web/entry-server-basic-renderer.js"),
    dest: resolve("packages/vue-server-renderer/basic.js"),
    format: "umd",
    env: "development",
    moduleName: "renderVueComponentToString",
    plugins: [node(), cjs()],
  },
  "web-server-renderer-webpack-server-plugin": {
    entry: resolve("server/webpack-plugin/server.js"),
    dest: resolve("packages/vue-server-renderer/server-plugin.js"),
    format: "cjs",
    external: Object.keys(
      require("../packages/vue-server-renderer/package.json").dependencies
    ),
  },
  "web-server-renderer-webpack-client-plugin": {
    entry: resolve("server/webpack-plugin/client.js"),
    dest: resolve("packages/vue-server-renderer/client-plugin.js"),
    format: "cjs",
    external: Object.keys(
      require("../packages/vue-server-renderer/package.json").dependencies
    ),
  },
  // Weex runtime factory
  "weex-factory": {
    weex: true,
    entry: resolve("weex/entry-runtime-factory.js"),
    dest: resolve("packages/weex-vue-framework/factory.js"),
    format: "cjs",
    plugins: [weexFactoryPlugin],
  },
  // Weex runtime framework (CommonJS).
  "weex-framework": {
    weex: true,
    entry: resolve("weex/entry-framework.js"),
    dest: resolve("packages/weex-vue-framework/index.js"),
    format: "cjs",
  },
  // Weex compiler (CommonJS). Used by Weex's Webpack loader.
  "weex-compiler": {
    weex: true,
    entry: resolve("weex/entry-compiler.js"),
    dest: resolve("packages/weex-template-compiler/build.js"),
    format: "cjs",
    external: Object.keys(
      require("../packages/weex-template-compiler/package.json").dependencies
    ),
  },
};
// 函数内部实现
function genConfig(name) {
  const opts = builds[name];
  const config = {
    input: opts.entry,
    external: opts.external,
    plugins: [flow(), alias(Object.assign({}, aliases, opts.alias))].concat(
      opts.plugins || []
    ),
    output: {
      file: opts.dest,
      format: opts.format,
      banner: opts.banner,
      name: opts.moduleName || "Vue",
    },
    onwarn: (msg, warn) => {
      if (!/Circular/.test(msg)) {
        warn(msg);
      }
    },
  };

  // built-in vars
  const vars = {
    __WEEX__: !!opts.weex,
    __WEEX_VERSION__: weexVersion,
    __VERSION__: version,
  };
  // feature flags
  Object.keys(featureFlags).forEach((key) => {
    vars[`process.env.${key}`] = featureFlags[key];
  });
  // build-specific env
  if (opts.env) {
    vars["process.env.NODE_ENV"] = JSON.stringify(opts.env);
  }
  config.plugins.push(replace(vars));

  if (opts.transpile !== false) {
    config.plugins.push(buble());
  }

  Object.defineProperty(config, "_name", {
    enumerable: false,
    value: name,
  });

  return config;
}

// 环境变量
if (process.env.TARGET) {
  // 配置函数
  module.exports = genConfig(process.env.TARGET);
} else {
  exports.getBuild = genConfig;
  exports.getAllBuilds = () => Object.keys(builds).map(genConfig);
}
